﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using NHibernate;
using NHibernate.Criterion;
using System.Web.UI.WebControls;
using mscook.core.components;
using mscook.core.domain;
using Iesi.Collections.Generic;
using NHibernate.Linq;
//CreateAlias 返回值还是当前的Criteria，但是CreateCriteria返回的新的Criteria。
namespace mscook.core.repositories
{
    public class Repository<T> : IRepository<T> where T : Entity
    {
        public Repository()
        {

        }
        protected virtual ISession Session
        {
            get { return SessionBuilder.CreateSession(); }
        }

        public virtual T Load(string id)
        {
            try
            {
                T reslut = Session.Load<T>(id);
                if (reslut == null)
                    throw new Exception("返回实体为空");
                else
                    return reslut;
            }
            catch (Exception ex)
            {
                throw new Exception("获取实体失败", ex);
            }
        }
        public virtual T Get(string id)
        {
            if (String.IsNullOrEmpty(id))
                return null;
            return Session.Get<T>(id);
        }

        //2010-12-16尹福青修改将CreateTime索引去掉，优化时间
        public virtual IList<T> GetAll()
        {
            return Session.CreateCriteria<T>()
                .Add(Expression.Eq("IsDelete", false))
                 .AddOrder(Order.Asc("CreateTime"))
                .List<T>();
        }
        public virtual void DeleteAll(IList<T> list)
        {
            try
            {
                foreach (T t in list)
                {
                    t.IsDelete = true;
                    Session.Update(t);
                    Session.Flush();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("删除全部实体失败", ex);
            }
        }
        public virtual void DeleteAll(Iesi.Collections.Generic.ISet<T> list)
        {
            try
            {
                foreach (T t in list)
                {
                    t.IsDelete = true;
                    Session.Update(t);
                    Session.Flush();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("删除全部实体失败", ex);
            }
        }

        public virtual void SaveOrUpdate(T entity)
        {
            try
            {
                Session.SaveOrUpdate(entity);
                Session.Flush();
            }
            catch (Exception ex)
            {
                throw new Exception("插入实体失败", ex);
            }
        }

        public virtual void Update(T entity)
        {
            try
            {
                Session.Update(entity);
                Session.Flush();
            }
            catch (Exception ex)
            {
                throw new Exception("更新实体失败", ex);
            }
        }

        public virtual void PhysicsDelete(string id)
        {
            try
            {
                var entity = Get(id);
                Session.Delete(entity);
                Session.Flush();
            }
            catch (System.Exception ex)
            {
                throw new Exception("物理删除实体失败", ex);
            }
        }

        public virtual bool Delete(string id)
        {

            var entity = Get(id);
            if (entity == null)
            {
                return false;
            }
            entity.IsDelete = true;
            Update(entity);
            return true;
        }
        //20130415  庞夫星  重载  int  for  PropID and PropValue
        public virtual T Load(int id)
        {
            try
            {
                T reslut = Session.Load<T>(id);
                if (reslut == null)
                    throw new Exception("返回实体为空");
                else
                    return reslut;
            }
            catch (Exception ex)
            {
                throw new Exception("获取实体失败", ex);
            }
        }
        //20130415  庞夫星  重载  int  for  PropID and PropValue
        public virtual void Delete(int id)
        {
            try
            {
                var entity = Get(id);
                entity.IsDelete = true;
                Update(entity);
            }
            catch (System.Exception ex)
            {
                throw new Exception("删除实体失败", ex);
            }
        }
        //20130415  庞夫星  重载  int  for  PropID and PropValue
        public virtual T Get(int id)
        {
            try
            {
                T reslut = Session.Get<T>(id);
                if (reslut == null)
                    throw new Exception("返回实体为空");
                else
                    return reslut;
            }
            catch (Exception ex)
            {
                throw new Exception("获取实体失败", ex);
            }
        }

        private string GetComparison(string comparison)
        {
            string res = string.Empty;
            switch (comparison)
            {
                case "lt":
                    res = "<";
                    break;
                case "gt":
                    res = ">";
                    break;
                case "eq":
                    res = "=";
                    break;
            }
            return res;
        }

        [Obsolete("GetPageList is deprecated, please use SelectPageList instead.")]
        public IList<T> GetPageList(int start, int limit, out long total)
        {
            var query = (from x in this.Session.Query<T>() select x)
               .Where(o => o.IsDelete == false
               )
               .OrderByDescending(o => o.CreateTime)
              ;
            total = query.LongCount();

            return query.Skip(start).Take(limit).ToList<T>();
        }

        /*Author:WeiXiaoXing*/
        /// <summary>
        /// 包含检查的分页查询，如果start 超过 total,则返回最后一页数据
        /// </summary>
        /// <param name="start"></param>
        /// <param name="limit"></param>
        /// <param name="total"></param>
        /// <returns></returns>
        public IList<T> SelectPageList(int start, int limit, out long total)
        {

            var query = (from x in this.Session.Query<T>() select x)
               .Where(o => o.IsDelete == false
               ).OrderByDescending(o=>o.EntityIndex)
               .OrderByDescending(o=>o.CreateTime);

            total = query.LongCount();

            if (start > total)
            {
                int tempStart = Int32.Parse(total.ToString()) - limit;
                return query.Skip(tempStart).Take(limit).ToList<T>();
            }
            return query.Skip(start).Take(limit).ToList<T>();
        }


        public IList<T> SelectPageList(int start, int limit, out long total,System.Linq.Expressions.Expression<Func<T, bool>> expression)
        {
            var query = (from x in this.Session.Query<T>() select x)
              .Where(o => o.IsDelete == false
              );

            query = query.Where(expression).OrderByDescending(o=>o.EntityIndex).OrderByDescending(o=>o.CreateTime);

            total = query.LongCount();

            if (start > total)
            {
                int tempStart = Int32.Parse(total.ToString()) - limit;
                return query.Skip(tempStart).Take(limit).ToList<T>();
            }
            return query.Skip(start).Take(limit).ToList<T>();
        }

        public IList<T> GetLimitByIds(IList<string> ids, int start, int limit, out long total)
        {
            var query = (from x in this.Session.Query<T>()
                         where x.IsDelete == false
                         && ids.Contains(x.Id)
                         select x);

            total = query.Count();
            return query.OrderByDescending(o => o.EntityIndex).OrderByDescending(o => o.CreateTime).Skip(start).Take(limit).ToList();
        }
        public IList<T> GetAllByIds(IList<string> ids)
        {
            var query = (from x in this.Session.Query<T>()
                         where x.IsDelete == false
                         && ids.Contains(x.Id)
                         select x);
            return query.OrderByDescending(o => o.CreateTime).ToList();
        }
    }

}
